#include "task.hpp"

//将线程编号转16进制
std::string switchPthreadId(pthread_t id)
{
    char* str = new char[32];
    snprintf(str, 32, "0x%x", id);
    return str;
}

//消费
void* consumer(void* args)
{
    // BlockQueue<int>* bp = static_cast<BlockQueue<int>*>(args);
    BlockQueue<Task>* bp = static_cast<BlockQueue<Task>*>(args);

    while(true)
    {
        // sleep(1);
        // int data = 0;
        Task t;

        // 1. 将数据从blockqueue中获取 -- 获取到了数据
        // bp->pop(&data);
        bp->pop(&t);
        // 2. 结合某种业务逻辑，处理数据！
        //运算
        t();

        // std::cout << "consumer get data:" << data << std::endl;
        std::cout << switchPthreadId(pthread_self()) << " | consumer data: " << t.formatArg() << t.formatRes() << std::endl;
    }
}

//生产
void* productor(void* args)
{
    // BlockQueue<int>* bp = static_cast<BlockQueue<int>*>(args);
    BlockQueue<Task>* bp = static_cast<BlockQueue<Task>*>(args);

    std::string ops = "+-*/%"; 

    while(true)
    {
        sleep(1);
        // 1. 先通过某种渠道获取数据
        // int data = rand() % 10 + 1; 
        char op = ops[rand() % ops.size()]; //取随机运算符
        int x = rand() % 20 + 1;
        int y = rand() % 10 + 1;
         
        //获取数据
        Task t(x, y, op);

        // 2. 将数据推送到blockqueue -- 完成生产过程
        // bp->push(data);
        bp->push(t);

        // std::cout << "productor data:" << data << std::endl;
        std::cout << switchPthreadId(pthread_self()) << " | productor Task: " <<  t.formatArg() << "?" << std::endl;
    }
}

int main()
{
    //生产随机数
    srand((uint64_t)time(nullptr) ^ getpid());

    //321原则：3种关系、2个角色、1个场所
    //创建阻塞队列
    // BlockQueue<int>* bq = new BlockQueue<int>();
    BlockQueue<Task>* bq = new BlockQueue<Task>();

    //生产消费模型
    pthread_t p[2],c[3];

    pthread_create(p, nullptr, productor,bq);
    pthread_create(p + 1, nullptr, productor,bq);

    pthread_create(c, nullptr, consumer,bq);
    pthread_create(c + 1, nullptr, consumer,bq);
    pthread_create(c + 2, nullptr, consumer,bq);
    


    pthread_join(c[0], nullptr);
    pthread_join(c[1], nullptr);
    pthread_join(p[0], nullptr);
    pthread_join(p[1], nullptr);
    pthread_join(p[2], nullptr);

    return 0;
}